﻿using DotNetCore.CAP;
using Hangfire;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.EmailHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.RecurringJobs;
using NP.BPMReportPlatform.RecurringJobs.Dto;
using NP.Enterprise.Utils.Http;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using static NP.BPMReportPlatform.Performance.Dto.PerformanceDto;
using static NP.BPMReportPlatform.RecurringJobs.Dto.SFPerformDto;
using static NP.BPMReportPlatform.RecurringJobs.Dto.SFPerformDto.SFFormTitleResponse;

namespace NP.BPMReportPlatform.SF
{
    /// <summary>
    /// 绩效考评SF同步
    /// </summary>
    public class SFPerformanceSyncJob : BpmReportPlatformRecurringJob, ISFPerformanceSyncJob
    {
        private readonly INPRestHttpHelper _nPRestHttp;
        private readonly SqlSugarClient _db, _dbPlatform;
        private readonly IEmailAPPService _emailAPPService;
        private readonly ICapPublisher _capBus;
        private readonly string _sourceSystem = "BPMNEW";
        private readonly string _esbSFTodoGetUrl;
        private readonly string _esbSFGetUrl;
        private readonly string _esbSFTokenUrl;
        private readonly string _esbSFPostUrl;
        private readonly string _companyId;
        private readonly string _privatekey;
        private readonly string _clientId;
        private readonly string _tokenUrl;

        public SFPerformanceSyncJob(ISqlSugarAppService sqlSugarAppService,
            INPRestHttpHelper httpClient, IConfiguration configuration, IEmailAPPService emailAPPService
            , ICapPublisher capPublisher)
        {
            _nPRestHttp = httpClient;
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _emailAPPService = emailAPPService;
            _capBus = capPublisher;
            _esbSFGetUrl = configuration["Nippon:ESB:sfDetailUrl"];
            _esbSFTokenUrl = configuration["Nippon:ESB:sfTokenUrl"];
            _esbSFTodoGetUrl = configuration["Nippon:ESB:sfToDoUrl"];
            _esbSFPostUrl = configuration["Nippon:ESB:sfPostUrl"];
            _clientId = configuration["Nippon:SF:client_id"];
            _companyId = configuration["Nippon:SF:company_id"];
            _privatekey = configuration["Nippon:SF:private_key"];
            _tokenUrl = configuration["Nippon:SF:token_url"];

        }

        /// <summary>
        /// 定时清理待办
        /// </summary>
        /// <returns></returns>
        public async Task SyncCategoryData()
        {
            var todoids = _db.Queryable<PerformanceEntity>().Where(t => t.ApproveResult == 1).Select(t => t.TodoEntryId).ToList();
            foreach (var item in todoids)
            {
                await CheckToDoData(item);
            }

            // 更新表单数据
            await UpdateFormData();
        }

        /// <summary>
        /// 间隔10分钟，获取待办（增加超时锁，60分钟）
        /// </summary>
        /// <returns></returns>
        [DisableConcurrentExecution(timeoutInSeconds: 60 * 60)]
        public async Task<string> SyncToDoData()
        {
            string msgResult = "---- SyncToDoData  Success  ---------";
            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_TodoEntryVTwoThree_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
                };

                var time = _db.Queryable<PerformanceEntity>().Max(t => t.LastModifiedDateTime);
                if (time == null)
                {
                    time = DateTime.Now.AddMonths(-1);
                }
                else
                {
                    time = time.Value.AddHours(-8);// 时区问题，减8H
                }

                var users = _dbPlatform.Queryable<Users>().Select(t => new { t.UserName, t.WorkNumber, t.FullPathText }).ToList();
                var userextens = _dbPlatform.Queryable<UserExtension>().Select(t => new { t.Sapemployeeid, t.Employeepostname }).ToList();
                var templates = _db.Queryable<PerformTemplateEntity>().Where(t => t.Status == true).ToList();
                int count = 1000;
                int skip = 0;
                List<PerformanceEntity> needAdds = new List<PerformanceEntity>();
                while (count == 1000)
                {
                    // 总是挂，间隔500s再请求
                    Thread.Sleep(500);
                    var requestBody = new
                    {
                        ___top = count,
                        ___skip = skip,
                        ___format = "json",
                        ___filter = $"categoryId in '0','2' and status eq '2' and lastModifiedDateTime ge '{time.Value.ToString("yyyy-MM-dd")}T{time.Value.ToString("HH:mm:ss")}'",
                        ___expand = "formContentNav/formHeader,formContentNav/formHeader/formTemplate",
                        ___select = "categoryId,todoEntryId,userId,lastModifiedDateTime,linkUrl,mobileLinkUrl,todoEntryName,categoryLabel,formContentNav/formHeader/formTitle,formContentNav/formHeader/currentStep,formContentNav/formHeader/formTemplateId,formContentNav/formHeader/formDataId,subjectId,formContentNav/formHeader/formTemplate/formTemplateName",
                        ___orderby = "lastModifiedDateTime"
                    };
                    var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
                    var result = await _nPRestHttp.ESBPostAsync<SFToDoResponse.SFToDo>(_esbSFTodoGetUrl, requestBodyStr, dic);
                    count = result?.d?.results?.Count() ?? 0;
                    skip = skip + 1000;
                    if (count > 0)
                    {
                        // 数据处理
                        foreach (var item in result?.d?.results)
                        {
                            if (!string.IsNullOrEmpty(item.userId) && item.userId.Contains("-"))
                            {
                                item.userId = item.userId.Split("-")[0];
                            }
                            var formHeader = item.formContentNav?.results?.FirstOrDefault()?.formHeader;
                            var username = users.FirstOrDefault(t => t.WorkNumber == item.userId)?.UserName;
                            if (formHeader == null || string.IsNullOrEmpty(username) || item.todoEntryName == "绩效校准")
                            {
                                continue;
                            }

                            // 处理一下，默认0的都是绩效，2的是其它
                            string formtemplatename = formHeader.formTemplate?.formTemplateName;
                            if (!string.IsNullOrEmpty(formtemplatename) && (formtemplatename.Contains("绩效计划") || formtemplatename.Contains("绩效评估")))
                            {
                                item.categoryId = 0;
                            }
                            else
                            {
                                item.categoryId = 2;
                            }

                            var template = templates.FirstOrDefault(s => s.FormTemplateId == formHeader.formTemplateId);
                            if (needAdds.Count(t => t.TodoEntryId == item.todoEntryId) == 0)
                            {
                                needAdds.Add(new PerformanceEntity()
                                {
                                    TodoEntryId = item.todoEntryId,
                                    CategoryId = item.categoryId,
                                    CategoryLabel = item.categoryLabel,
                                    LastModifiedDateTime = ToSFDateTime(item.lastModifiedDateTime),
                                    TodoEntryName = item.todoEntryName,
                                    FormDataId = formHeader.formDataId,
                                    FormTemplateId = formHeader.formTemplateId,
                                    FormTitle = formHeader.formTitle,
                                    WorkNumber = item.userId,
                                    UserName = username,
                                    LinkUrl = item.linkUrl,
                                    SubjectId = item.subjectId,
                                    SubjectName = users.FirstOrDefault(t => t.WorkNumber == item.subjectId)?.UserName,
                                    IsOpenUrl = template == null,
                                    TemplateTypeName = template?.FormTemplateTypeName,
                                    CreateTime = DateTime.Now,
                                    ApproveResult = 1,
                                    FormTemplateName = formHeader.formTemplate?.formTemplateName
                                });
                            }
                        }
                    }
                }

                if (needAdds.Count() > 0)
                {
                    var x = _db.Storageable(needAdds).ToStorage();
                    x.AsInsertable.ExecuteCommand();//不存在则插入,不更新

                    // 获取插入行,且需要下载数据的
                    var insertList = x.InsertList.Select(z => z.Item).Where(t => t.IsOpenUrl == false).ToList();
                    if (insertList.Count() > 0)
                    {
                        await GetBusinessData(insertList);
                    }

                    // TODO 邮件通知
                    if (x.InsertList.Select(z => z.Item).ToList().Count() > 0)
                    {
                        var list = x.InsertList.Select(z => z.Item).ToList();
                        var todoenrryids = list.Select(t => t.TodoEntryId).ToList();

                        // 如果是同一个待办，只是因为formContentId变了，则不通知
                        foreach (var item in list)
                        {
                            // 找到审批过的次数
                            var sameApprove = _db.Queryable<PerformanceEntity>()
                                .Where(t => t.ApproveResult == 1 &&
                                t.FormDataId == item.FormDataId &&
                                t.WorkNumber == item.WorkNumber &&
                                t.TodoEntryName == item.TodoEntryName && t.TodoEntryId != item.TodoEntryId).First();
                            if (sameApprove != null)
                            {
                                // 更新暂存的逻辑
                                sameApprove.ApproveResult = -1;
                                var savedata = _db.Queryable<PerformFormKeyDataEntity>().Where(t => t.TodoEntryId == sameApprove.TodoEntryId).First();
                                if (savedata != null)
                                {
                                    savedata = new PerformFormKeyDataEntity()
                                    {
                                        TodoEntryId = item.TodoEntryId,
                                        FormKeyData = savedata.FormKeyData,
                                    };
                                    _db.Insertable(savedata).ExecuteCommand();
                                }
                                _db.Updateable(sameApprove).ExecuteCommand();
                            }
                            else
                            {
                                // 推送邮件
                                SendEmailList(item);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                msgResult = "---- SyncToDoData  Failed  ---------" + ex.Message;
            }

            return msgResult;
        }

        /// <summary>
        /// 异常结束的待办重新激活
        /// </summary>
        /// <returns></returns>
        public async Task<string> SyncToDoUpdateData()
        {
            string msgResult = "---- SyncToDoUpdateData  Success  ---------";
            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_TodoEntryVTwoThree_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
                };

                var templates = _db.Queryable<PerformTemplateEntity>().Where(t => t.Status == true).ToList();
                string templateidstr = "";
                templates.ForEach(t =>
                {
                    templateidstr += "'" + t.FormTemplateId + "',";
                });
                templateidstr = templateidstr.TrimEnd(',');

                int count = 1000;
                int skip = 0;
                List<int> needAdds = new List<int>();
                while (count == 1000)
                {
                    // 总是挂，间隔500s再请求
                    Thread.Sleep(500);
                    var requestBody = new
                    {
                        ___top = count,
                        ___skip = skip,
                        ___format = "json",
                        ___filter = $"categoryId eq '0' and status eq '2' and formTemplateId in {templateidstr}",
                        ___expand = "formContentNav/formHeader,formContentNav/formHeader/formTemplate",
                        ___select = "todoEntryId",
                        ___orderby = "lastModifiedDateTime"
                    };
                    var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
                    var result = await _nPRestHttp.ESBPostAsync<SFToDoResponse.SFToDo>(_esbSFTodoGetUrl, requestBodyStr, dic);
                    count = result?.d?.results?.Count() ?? 0;
                    skip = skip + 1000;
                    if (count > 0)
                    {
                        // 数据处理
                        foreach (var item in result?.d?.results)
                        {

                            needAdds.Add(item.todoEntryId);
                        }
                    }
                }

                if (needAdds.Count() > 0)
                {
                    var needUpdates = _db.Queryable<PerformanceEntity>().Where(t => SqlFunc.ContainsArray(needAdds, t.TodoEntryId) && t.ApproveResult != 1).ToList();

                    // TODO 邮件通知
                    if (needUpdates.Count() > 0)
                    {
                        // 如果是同一个待办，只是因为formContentId变了，则不通知
                        foreach (var item in needUpdates)
                        {
                            item.ApproveResult = 1;
                            item.ApproveMessage = string.Empty;
                            item.ApproveDate = null;
                            // 推送邮件, 绩效计划的排除
                            if (!item.FormTitle.Contains("绩效计划"))
                            {
                                SendEmailList(item);
                            }
                        }
                        _db.Updateable(needUpdates).ExecuteCommand();
                    }
                }
            }
            catch (Exception ex)
            {
                msgResult = "---- SyncToDoUpdateData  Failed  ---------" + ex.Message;
            }

            return msgResult;
        }

        /// <summary>
        /// 全量抓取2024年以后得待办
        /// </summary>
        /// <returns></returns>
        public async Task<string> GetAllNeedAddTodoData()
        {
            string msgResult = "---- GetAllNeedAddTodoData Success  ---------";
            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_TodoEntryVTwoThree_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
                };

                int count = 1000;
                int skip = 0;
                var users = _dbPlatform.Queryable<Users>().Select(t => new { t.UserName, t.WorkNumber, t.FullPathText }).ToList();
                var userextens = _dbPlatform.Queryable<UserExtension>().Select(t => new { t.Sapemployeeid, t.Employeepostname }).ToList();
                var templates = _db.Queryable<PerformTemplateEntity>().Where(t => t.Status == true).ToList();
                List<PerformanceEntity> needAdds = new List<PerformanceEntity>();
                while (count == 1000)
                {
                    // 总是挂，间隔500s再请求
                    Thread.Sleep(500);
                    var requestBody = new
                    {
                        ___top = count,
                        ___skip = skip,
                        ___format = "json",
                        ___filter = $"categoryId eq '0' and status eq '2' and lastModifiedDateTime ge '2024-01-01T00:00:00'",
                        ___expand = "formContentNav/formHeader,formContentNav/formHeader/formTemplate",
                        ___select = "categoryId,todoEntryId,userId,lastModifiedDateTime,linkUrl,mobileLinkUrl,todoEntryName,categoryLabel,formContentNav/formHeader/formTitle,formContentNav/formHeader/currentStep,formContentNav/formHeader/formTemplateId,formContentNav/formHeader/formDataId,subjectId,formContentNav/formHeader/formTemplate/formTemplateName",
                        ___orderby = "lastModifiedDateTime"
                    };
                    var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
                    var result = await _nPRestHttp.ESBPostAsync<SFToDoResponse.SFToDo>(_esbSFTodoGetUrl, requestBodyStr, dic);
                    count = result?.d?.results?.Count() ?? 0;
                    skip = skip + 1000;
                    if (count > 0)
                    {
                        // 数据处理
                        foreach (var item in result?.d?.results)
                        {
                            if (!string.IsNullOrEmpty(item.userId) && item.userId.Contains("-"))
                            {
                                item.userId = item.userId.Split("-")[0];
                            }
                            var formHeader = item.formContentNav?.results?.FirstOrDefault()?.formHeader;
                            var username = users.FirstOrDefault(t => t.WorkNumber == item.userId)?.UserName;
                            if (formHeader == null || string.IsNullOrEmpty(username) || item.todoEntryName == "绩效校准")
                            {
                                continue;
                            }

                            var template = templates.FirstOrDefault(s => s.FormTemplateId == formHeader.formTemplateId);
                            needAdds.Add(new PerformanceEntity()
                            {
                                TodoEntryId = item.todoEntryId,
                                CategoryId = item.categoryId,
                                CategoryLabel = item.categoryLabel,
                                LastModifiedDateTime = ToSFDateTime(item.lastModifiedDateTime),
                                TodoEntryName = item.todoEntryName,
                                FormDataId = formHeader.formDataId,
                                FormTemplateId = formHeader.formTemplateId,
                                FormTitle = formHeader.formTitle,
                                WorkNumber = item.userId,
                                UserName = username,
                                LinkUrl = item.linkUrl,
                                SubjectId = item.subjectId,
                                SubjectName = users.FirstOrDefault(t => t.WorkNumber == item.subjectId)?.UserName,
                                IsOpenUrl = template == null,
                                TemplateTypeName = template?.FormTemplateTypeName,
                                CreateTime = DateTime.Now,
                                ApproveResult = 1,
                                FormTemplateName = formHeader.formTemplate?.formTemplateName
                            });
                        }
                    }
                }

                if (needAdds.Count() > 0)
                {
                    var x = _db.Storageable(needAdds).ToStorage();
                    x.AsInsertable.ExecuteCommand();//不存在则插入,不更新

                    // 获取插入行,且需要下载数据的
                    var insertList = x.InsertList.Select(z => z.Item).Where(t => t.IsOpenUrl == false).ToList();
                    if (insertList.Count() > 0)
                    {
                        await GetBusinessData(insertList);
                    }

                    // 邮件通知
                    if (x.InsertList.Select(z => z.Item).ToList().Count() > 0)
                    {
                        var list = x.InsertList.Select(z => z.Item).ToList();
                        var todoenrryids = list.Select(t => t.TodoEntryId).ToList();

                        // 如果是同一个待办，只是因为formContentId变了，则不通知
                        foreach (var item in list)
                        {
                            // 找到审批过的次数
                            var sameApprove = _db.Queryable<PerformanceEntity>()
                                .Where(t => t.ApproveResult == 1 &&
                                t.FormDataId == item.FormDataId &&
                                t.WorkNumber == item.WorkNumber &&
                                t.TodoEntryName == item.TodoEntryName && t.TodoEntryId != item.TodoEntryId).First();
                            if (sameApprove != null)
                            {
                                // 更新暂存的逻辑
                                sameApprove.ApproveResult = -1;
                                var savedata = _db.Queryable<PerformFormKeyDataEntity>().Where(t => t.TodoEntryId == sameApprove.TodoEntryId).First();
                                if (savedata != null)
                                {
                                    savedata = new PerformFormKeyDataEntity()
                                    {
                                        TodoEntryId = item.TodoEntryId,
                                        FormKeyData = savedata.FormKeyData,
                                    };
                                    _db.Insertable(savedata).ExecuteCommand();
                                }
                                _db.Updateable(sameApprove).ExecuteCommand();
                            }
                            else
                            {
                                // 推送邮件
                                SendEmailList(item);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                msgResult = "---- GetAllNeedAddTodoData  Failed  ---------" + ex.Message;
            }

            return msgResult;
        }

        /// <summary>
        /// 更新表单数据，防止数据默默未插入成功
        /// </summary>
        /// <returns></returns>
        public async Task<string> UpdateFormData()
        {
            var totalids = _db.Queryable<PerformFormDataEntity>().Select(t => t.TodoEntryId).ToList();
            // 修复，只处理激活中的待办
            var lists = _db.Queryable<PerformanceEntity>().Where(t => !SqlFunc.ContainsArray(totalids, t.TodoEntryId) && t.ApproveResult ==1 && t.IsOpenUrl == false).ToList();
            if (lists.Count() > 0)
            {
                foreach (var item in lists)
                {
                    GetBusinessData(new List<PerformanceEntity>() { item });
                    Thread.Sleep(500);
                }
            }
            return "成功";
        }

        /// <summary>
        /// 补发批量待办失败的邮件
        /// </summary>
        /// <returns></returns>
        public async Task<string> SendExtarEmail()
        {
            //            DateTime start = DateTime.Parse("2024-11-13 19:29:40");
            //            DateTime end = DateTime.Parse("2024-11-13 19:49:40");
            //            var sqlstr = @"select substring_index(substring_index(Content,'""To"":""',-1),'"",""CC""',1) as email,
            //substring_index(substring_index(Content,'请勿回复]',-1),'"",""Body""',1) as title from `cap.published` WHERE NAME='bpmnew.EmailAppService.SendEmailAsync' 
            //and Content like '%2024年度-绩效评估%' and Added > '2024-11-13 19:20:40' 
            //and Added < '2024-11-14 06:00:40'";
            //            var emails = _db.SqlQueryable<TestEmailDto>(sqlstr).ToList().Select(t => t.email).ToList();
            //            var worknumbers = _dbPlatform.Queryable<Users>().Where(t => emails.Contains(t.Email)).Select(t => t.WorkNumber).ToList();
            //            var data = _db.Queryable<PerformanceEntity>().Where(t => t.CreateTime > start
            //            && t.CreateTime < end && t.SubjectId == t.WorkNumber && t.FormTitle.Contains("2024年度-绩效评估") && t.ApproveResult == 1).ToList();

            //            if (data.Count() > 0)
            //            {
            //                foreach (var item in data)
            //                {
            //                    if (!worknumbers.Contains(item.WorkNumber))
            //                    {
            //                        SendEmailList(item, true);
            //                    }
            //                }
            //            }
            //            return data.Count().ToString();
            return "关闭";
        }


        /// <summary>
        /// 催办
        /// </summary>
        /// <param name="id"></param>
        public void SendEmail(List<int> id)
        {
            var data = _db.Queryable<PerformanceEntity>().Where(t => id.Contains(t.TodoEntryId)).ToList();
            if (data.Count() > 0)
            {
                foreach (var item in data)
                {
                    SendEmailList(item, true);
                }
            }
        }

        /// <summary>
        /// 推送邮件，或催办
        /// </summary>
        private void SendEmailList(PerformanceEntity item, bool isUrging = false)
        {
            if (item == null)
            {
                return;
            }
            try
            {
                if (item.CategoryId == 2)
                {
                    SendOtherEmailList(item, isUrging);
                    return;
                }
                string to = string.Empty;
                string topic = string.Empty;
                string templateName = "PerformanceNotice.cshtml";
                string url = ConfigManager.HRBPMReportUrl + "/performance/performance-list";
                string formtitle = item.FormTemplateName;
                var titles = item.FormTemplateName.Split("-");
                if (titles.Count() > 1)
                {
                    formtitle = item.SubjectName + " " + titles[0] + "-" + titles[1];
                }

                to = _dbPlatform.Queryable<Users>().Where(t => t.WorkNumber == item.WorkNumber).First()?.Email;
                topic = $"[系统邮件，请勿回复]{formtitle}的待办通知";

                string content = string.Empty;
                string reason = string.Empty;
                bool showReason = false;
                // 不是催办
                if (!isUrging && item.IsOpenUrl == false)
                {
                    // 找找看，待办是不是从下一步退回的
                    var steps = _db.Queryable<PerformStepEntity>().Where(t => t.FormDataId == item.FormDataId).ToList();
                    var nexstep = steps.Where(t => item.TodoEntryName == t.StepName).First()?.StepNumber + 1;
                    var worknumbers = steps.Where(t => t.StepNumber == nexstep).Select(t => t.WorkNumber).ToList();
                    if (worknumbers != null && worknumbers.Count() > 0)
                    {
                        var performance = _db.Queryable<PerformanceEntity>()
                        .Where(b => b.FormDataId == item.FormDataId && worknumbers.Contains(b.WorkNumber) && b.ApproveResult == 4)
                        .OrderBy(t => t.CreateTime, OrderByType.Desc).First();
                        if (performance != null)
                        {
                            reason = _db.Queryable<PerformFormKeyDataEntity>().Where(t => t.TodoEntryId == performance.TodoEntryId).First()?.Record1;
                            showReason = !string.IsNullOrEmpty(reason);
                        }
                    }
                }

                var oc = new { UserName = item.UserName, FormTitle = formtitle, Url = url, Display = showReason ? "block" : "none", Reason = reason };

                if (!string.IsNullOrEmpty(templateName))
                {
                    content = _emailAPPService.GenerateEmailTemplate(templateName, oc);
                }

                if (!string.IsNullOrEmpty(content) && !string.IsNullOrEmpty(to))
                {
                    // TODO: 测试，只发给liya,上线前要去掉
                    // topic = topic + ";" + to;
                    // to = "liya.li@movit-tech.com;tiger.zhou@movit-tech.com";
                    _capBus.PublishAsync("bpmnew.EmailAppService.SendEmailAsync",
                      new SendEmailSimpleDto()
                      {
                          To = to,
                          Subject = topic,
                          Body = content
                      });
                    Thread.Sleep(1000);
                }
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 推送邮件，或催办
        /// </summary>
        private void SendOtherEmailList(PerformanceEntity item, bool isUrging = false)
        {
            if (item == null)
            {
                return;
            }
            try
            {
                string to = string.Empty;
                string topic = string.Empty;
                string name = string.Empty;
                if (item.FormTemplateName.Contains("360评估"))
                {
                    name = "360";
                }
                else
                {
                    name = "Other";
                }
                string templateName = $"Performance{name}Notice.cshtml";
                string url = ConfigManager.HRBPMReportUrl + "/performance/performance-other-list";
                string formtitle = item.FormTitle;
                to = _dbPlatform.Queryable<Users>().Where(t => t.WorkNumber == item.WorkNumber).First()?.Email;
                topic = $"[系统邮件，请勿回复]{formtitle}的待办通知";

                string content = string.Empty;

                var oc = new { UserName = item.UserName, FormTitle = formtitle, Url = url };

                if (!string.IsNullOrEmpty(templateName))
                {
                    content = _emailAPPService.GenerateEmailTemplate(templateName, oc);
                }

                if (!string.IsNullOrEmpty(content) && !string.IsNullOrEmpty(to))
                {
                    // TODO: 测试，只发给liya,上线前要去掉
                    //topic = topic + ";" + to;
                    //to = "liya.li@movit-tech.com;tiger.zhou@movit-tech.com";
                    _capBus.PublishAsync("bpmnew.EmailAppService.SendEmailAsync",
                      new SendEmailSimpleDto()
                      {
                          To = to,
                          Subject = topic,
                          Body = content
                      });
                    Thread.Sleep(1000);
                }
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 定时获取待办 true:可以用 false：已作废，不能用
        /// </summary>
        /// <returns></returns>
        public async Task<bool> CheckToDoData(int todoEntryId)
        {
            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_TodoEntryVTwoThree_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
                };

                List<PerformanceEntity> needAdds = new List<PerformanceEntity>();
                var requestBody = new
                {
                    ___format = "json",
                    ___filter = $"categoryId eq '0' and status eq '2' and  todoEntryId eq '{todoEntryId}'",
                    ___select = "todoEntryId",
                    ___orderby = "lastModifiedDateTime"
                };
                var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
                var result = await _nPRestHttp.ESBPostAsync<SFToDoResponse.SFToDo>(_esbSFTodoGetUrl, requestBodyStr, dic);
                int count = result?.d?.results?.Count() ?? 0;
                if (count == 0 && result != null)
                {
                    var time = DateTime.Now;
                    // 说明已经被处理过了
                    _db.Updateable<PerformanceEntity>().SetColumns(t => new PerformanceEntity() { ApproveResult = 4, ApproveMessage = "已处理", ApproveDate = time }).Where(t => t.TodoEntryId == todoEntryId && t.ApproveResult == 1).ExecuteCommand();
                    return false;
                }
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 定时获取已办
        /// </summary>
        /// <returns></returns>
        public async Task<string> SyncDoneData()
        {
            string msgResult = "---- SyncDoneData  Success  ---------";
            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_TodoEntryVTwoFour_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
                };

                var time = _db.Queryable<PerformanceEntity>().Max(t => t.LastModifiedDateTime);
                if (time == null)
                {
                    time = DateTime.Now.AddMonths(-1);
                }

                int count = 1000;
                int skip = 0;
                List<int> needUpdates = new List<int>();
                while (count == 1000)
                {
                    // 总是挂，间隔500s再请求
                    Thread.Sleep(500);
                    var requestBody = new
                    {
                        ___top = count,
                        ___skip = skip,
                        ___format = "json",
                        ___filter = $"categoryId eq '0' and status eq '3' and lastModifiedDateTime ge '{time.Value.ToString("yyyy-MM-dd")}T{time.Value.ToString("HH-mm-ss")}'",
                        ___expand = "formContentNav/formHeader",
                        ___select = "todoEntryId",
                        ___orderby = "lastModifiedDateTime"
                    };
                    var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
                    var result = await _nPRestHttp.ESBPostAsync<SFToDoResponse.SFToDo>(_esbSFTodoGetUrl, requestBodyStr, dic);
                    count = result?.d?.results?.Count() ?? 0;
                    skip = skip + 1000;
                    if (count > 0)
                    {
                        // 数据处理
                        foreach (var item in result?.d?.results)
                        {
                            needUpdates.Add(item.todoEntryId);
                        }
                    }
                }

                if (needUpdates.Count() > 0)
                {
                    _db.Updateable<PerformanceEntity>()
                        .SetColumns(t => new PerformanceEntity() { ApproveResult = 4 })
                        .Where(t => needUpdates.Contains(t.TodoEntryId)).ExecuteCommand();
                }
            }
            catch (Exception ex)
            {
                msgResult = "---- SyncDoneData  Failed  ---------" + ex.Message;
            }

            return msgResult;
        }

        /// <summary>
        /// 获取每一个待办对应的表单信息和审批信息
        /// </summary>
        /// <returns></returns>
        public async Task GetBusinessData(List<PerformanceEntity> datas)
        {
            if (datas.Count() == 0)
            {
                return;
            }
            List<PerformFormDataEntity> needAddFormData = new List<PerformFormDataEntity>();
            List<PerformStepEntity> needAddStepData = new List<PerformStepEntity>();
            List<int> needDelete = new List<int>();
            foreach (var item in datas)
            {
                string token = GetToken(item.WorkNumber);
                // 1. 获取表单信息
                // 2. 获取审批步骤(只在员工自评环节拿)
                var fromdata = await GetFormTitle(item, token);
                if (fromdata != null)
                {
                    needAddFormData.Add(fromdata); // 业务目标
                }
                var stepdata = await GetFormStep(item.FormDataId, token); // 获取审批步骤
                if (stepdata.Count() > 0)
                {
                    if (!needDelete.Contains(item.FormDataId))
                    {
                        needAddStepData.AddRange(stepdata);
                    }
                    needDelete.Add(item.FormDataId);
                }
            }

            if (needAddFormData.Count() > 0)
            {
                var x = _db.Storageable(needAddFormData).ToStorage();
                x.AsInsertable.ExecuteCommand();//不存在则插入,不更新
                x.AsUpdateable.ExecuteCommand();//不存在则插入,更新
            }

            if (needAddStepData.Count() > 0)
            {
                _db.Deleteable<PerformStepEntity>().Where(t => needDelete.Contains(t.FormDataId)).ExecuteCommand();
                _db.Insertable(needAddStepData).ExecuteCommand();
            }
        }

        /// <summary>
        /// 推送评分结果
        /// </summary>
        /// <param name="sections"></param>
        /// <returns></returns>
        public PerformanceEntity SaveScope(Sections sections, int todoEntryId, out string token)
        {
            var todoData = _db.Queryable<PerformanceEntity>().Where(t => t.TodoEntryId == todoEntryId).First();
            token = GetToken(todoData.WorkNumber);
            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfPostAllFormInfo_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem },
                    { "Authorization", "Bearer "+ token }
                };

                // 数据整理
                var requestBody = new
                {
                    url = new { format = "json" },
                    body = new
                    {
                        __metadata = sections.__metadata,
                        objectiveSections = sections.objectiveSections.results.Where(t => t.objectives.results[0].customElement.results.Count() > 0).Select(t => new
                        {
                            __metadata = t.__metadata,
                            objectives = t.objectives.results.Where(t => t.customElement.results.Count() > 0).Select(ob => new
                            {
                                __metadata = ob.__metadata,
                                customElement = ob.customElement.results.Where(cus => !string.IsNullOrEmpty(cus.valueKey)).Select(cus => new
                                {
                                    __metadata = cus.__metadata,
                                    elementKey = cus.elementKey,
                                    sectionIndex = cus.sectionIndex,
                                    itemId = cus.itemId,
                                    formContentId = cus.formContentId,
                                    formDataId = cus.formDataId,
                                    type = cus.type,
                                    valueKey = cus.valueKey,
                                    value = cus.value
                                })
                            }),
                        }),
                        competencySections = sections.competencySections.results.Where(t => t.competencies.results[0].customElement.results.Count() > 0)
                        .Select(t => new
                        {
                            __metadata = t.__metadata,
                            competencies = t.competencies.results.Select(ob => new
                            {
                                __metadata = ob.__metadata,
                                customElement = ob.customElement.results.Where(cus => !string.IsNullOrEmpty(cus.valueKey)).Select(cus => new
                                {
                                    __metadata = cus.__metadata,
                                    elementKey = cus.elementKey,
                                    sectionIndex = cus.sectionIndex,
                                    itemId = cus.itemId,
                                    formContentId = cus.formContentId,
                                    formDataId = cus.formDataId,
                                    type = cus.type,
                                    valueKey = cus.valueKey,
                                    value = cus.value
                                })
                            }),
                        }),
                        customSections = sections.customSections.results.Where(t => t.customElement.results.Count() > 0).Select(t => new
                        {
                            __metadata = t.__metadata,
                            customElement = t.customElement.results.Where(cus => !string.IsNullOrEmpty(cus.valueKey)).Select(cus => new
                            {
                                __metadata = cus.__metadata,
                                elementKey = cus.elementKey,
                                sectionIndex = cus.sectionIndex,
                                itemId = cus.itemId,
                                formContentId = cus.formContentId,
                                formDataId = cus.formDataId,
                                type = cus.type,
                                valueKey = cus.valueKey,
                                value = cus.value
                            })
                        }),
                    },
                };
                var requeststr1 = JsonConvert.SerializeObject(requestBody).Replace("format", "$format");

                var resDataStr = _nPRestHttp.ESBPostAsync(_esbSFPostUrl, requeststr1, dic).Result;
                var resData = JsonConvert.DeserializeObject<SFPerformPushResponse.SFPerformPush>(resDataStr);

                // 数据处理
                if (resData?.d != null && resData?.d.Count > 0)
                {
                    todoData.ApproveResult = resData.d[0].status == "OK" ? 4 : 1;
                    todoData.ApproveMessage = resData.d[0].message;
                    todoData.ApproveDate = DateTime.Now;
                };
            }
            catch (Exception ex)
            {
                todoData.ApproveMessage = ex.Message;
                todoData.ApproveDate = DateTime.Now;
            }
            finally
            {
                if (todoData != null)
                {
                    _db.Updateable(todoData).UpdateColumns(t => new { t.ApproveResult, t.ApproveMessage, t.ApproveDate }).ExecuteCommand();
                }
            }

            return todoData;
        }

        /// <summary>
        /// 推送评分结果
        /// </summary>
        /// <param name="sections"></param>
        /// <returns></returns>
        public PerformanceEntity SuggestScope(Sections sections, int todoEntryId, out string token)
        {
            var todoData = _db.Queryable<PerformanceEntity>().Where(t => t.TodoEntryId == todoEntryId).First();
            token = GetToken(todoData.WorkNumber);
            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfPostAllFormInfo_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem },
                    { "Authorization", "Bearer "+ token }
                };

                // 数据整理
                var requestBody = new
                {
                    url = new { format = "json" },
                    body = new
                    {
                        __metadata = sections.__metadata,
                        customSections = sections.customSections.results.Where(t => t.sectionName == "员工本人确认" && t.customElement.results.Count() > 0).Select(t => new
                        {
                            __metadata = t.__metadata,
                            customElement = t.customElement.results.Where(cus => !string.IsNullOrEmpty(cus.valueKey)).Select(cus => new
                            {
                                __metadata = cus.__metadata,
                                elementKey = cus.elementKey,
                                sectionIndex = cus.sectionIndex,
                                itemId = cus.itemId,
                                formContentId = cus.formContentId,
                                formDataId = cus.formDataId,
                                valueKey = cus.valueKey,
                                value = cus.value,
                                ___checked = true
                            })
                        }),
                    },
                };
                var requeststr1 = JsonConvert.SerializeObject(requestBody).Replace("format", "$format").Replace("___checked", "checked");

                var resDataStr = _nPRestHttp.ESBPostAsync(_esbSFPostUrl, requeststr1, dic).Result;
                var resData = JsonConvert.DeserializeObject<SFPerformPushResponse.SFPerformPush>(resDataStr);

                // 数据处理
                if (resData?.d != null && resData?.d.Count > 0)
                {
                    todoData.ApproveResult = resData.d[0].status == "OK" ? 4 : 1;
                    todoData.ApproveMessage = resData.d[0].message;
                    todoData.ApproveDate = DateTime.Now;
                };
            }
            catch (Exception ex)
            {
                todoData.ApproveMessage = ex.Message;
                todoData.ApproveDate = DateTime.Now;
            }
            finally
            {
                if (todoData != null)
                {
                    _db.Updateable(todoData).UpdateColumns(t => new { t.ApproveResult, t.ApproveMessage, t.ApproveDate }).ExecuteCommand();
                }
            }

            return todoData;
        }

        /// <summary>
        /// 下一步
        /// </summary>
        /// <param name="todoEntryId"></param>
        /// <returns></returns>
        public async Task ApproveNext(PerformanceEntity entity, string token)
        {
            try
            {
                if (string.IsNullOrEmpty(token))
                {
                    token = GetToken(entity.WorkNumber);
                }
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfSendToNextStep_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem },
                    { "Authorization", "Bearer "+ token }
                };

                var requestBody = new
                {
                    ___format = "json",
                    formDataId = $"{entity.FormDataId}L",
                };
                var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
                var result = await _nPRestHttp.ESBPostAsync(_esbSFGetUrl, requestBodyStr, dic);
                if (!result.Contains("Success"))
                {
                    string locked = "The form was not routed because it is currently locked by other user";
                    if (result.Contains(locked))
                    {
                        entity.ApproveMessage = "由于有另一位审批人同时提交评分，请先点击暂存并关闭，待收到下一封待办邮件后进行评分并提交（此次评分等内容会自动保存）。";
                    }
                    else
                    {
                        entity.ApproveMessage = result;
                    }
                }
            }
            catch (Exception ex)
            {
                entity.ApproveMessage = "下一步：" + ex.Message;
            }
        }

        /// <summary>
        /// 上一步
        /// </summary>
        /// <param name="todoEntryId"></param>
        /// <returns></returns>
        public async Task ApprovePrev(PerformanceEntity entity, string token)
        {
            try
            {
                if (string.IsNullOrEmpty(token))
                {
                    token = GetToken(entity.WorkNumber);
                }
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfSendToPreviousStep_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem },
                    { "Authorization", "Bearer "+ token }
                };

                var requestBody = new
                {
                    ___format = "json",
                    formDataId = $"{entity.FormDataId}L",
                };
                var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
                var result = await _nPRestHttp.ESBPostAsync(_esbSFGetUrl, requestBodyStr, dic);
                if (!result.Contains("Success"))
                {
                    string locked = "The form was not routed because it is currently locked by other user";
                    if (result.Contains(locked))
                    {
                        entity.ApproveMessage = "由于有另一位审批人同时提交评分，请先点击暂存并关闭，待收到下一封待办邮件后进行评分并提交（此次评分等内容会自动保存）。";
                    }
                    else
                    {
                        entity.ApproveMessage = result;
                    }
                }
            }
            catch (Exception ex)
            {
                entity.ApproveMessage = "上一步：" + ex.Message;
            }
        }

        /// <summary>
        /// 根据工号获取历史绩效信息
        /// </summary>
        /// <returns></returns>
        public async Task<List<SFHistoryResponse.SFHistoryData>> GetHistoryData(string worknumber)
        {
            // 权限判断
            List<string> worknumbers = new List<string>();
            var currentWorkNumber = CurrentUser != null && CurrentUser.UserName != null ? CurrentUser.UserName : string.Empty;

            // 获取权限，先看是否有所有数据权限，这边通过额外配置，跟角色没关系
            // 默认添加管理员权限
            var adminroles = _dbPlatform.Queryable<Dictionaries>()
                             .Where(t => t.TypeCode == "ADMINROLE").Select(t => t.Value).ToList();
            if (!adminroles.Contains(currentWorkNumber))
            {
                // 权限过滤
                var deptcodes = _dbPlatform.Queryable<SFPositionUserRelEntity, SFApproverEntity>((a, b) => a.PositionCode == b.PositionCode)
                    .Where((a, b) => a.UserId == currentWorkNumber && b.RoleCode == "HRBP Performance").Select((a, b) => b.DeptCode).ToList();

                if (deptcodes != null && deptcodes.Count() > 0)
                {
                    worknumbers = _dbPlatform.Queryable<UserExtension>().Where(t => deptcodes.Contains(t.Objid_1) || deptcodes.Contains(t.Objid_2)
                    || deptcodes.Contains(t.Objid_3) || deptcodes.Contains(t.Objid_4) || deptcodes.Contains(t.Objid_5) || deptcodes.Contains(t.Objid_6)
                    || deptcodes.Contains(t.Objid_7) || deptcodes.Contains(t.Objid_8))
                        .Select(t => t.Sapemployeeid).ToList();
                }

                if (!worknumbers.Contains(worknumber))
                {
                    throw new Exception("您没有该员工的查询权限!");
                }
            }

            Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfGetPerformanceHistoryFormId_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
                };

            var templates = _db.Queryable<PerformTemplateEntity>().Where(t => t.Status == true).ToList();
            string templateidstr = "";
            templates.ForEach(t =>
            {
                templateidstr += "'" + t.FormTemplateId + "',";
            });
            templateidstr = templateidstr.TrimEnd(',');
            var requestBody = new
            {
                ___format = "json",
                ___filter = $"formSubjectId eq '{worknumber}' and formTemplateId in {templateidstr} and formDataStatus in '1','3'",
                ___select = "formDataId,formTitle,formTemplateId,formReviewStartDate,formLastModifiedDate,currentStep,formSubjectId,formReviewDueDate,formDataStatus,formReviewEndDate",
                ___orderby = "formLastModifiedDate desc"
            };
            var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
            var result = await _nPRestHttp.ESBPostAsync<SFHistoryResponse.SFHistory>(_esbSFTodoGetUrl, requestBodyStr, dic);

            // 数据处理
            foreach (var item in result?.d?.results)
            {
                item.formLastModifiedDate = ToSFDateTime(item.formLastModifiedDate).Value.ToString("yyyy-MM-dd HH:mm:ss");
                item.formTemplateName = templates.FirstOrDefault(s => s.FormTemplateId == item.formTemplateId)?.FormTemplateTypeName;
            }

            return result?.d?.results;
        }

        /// <summary>
        /// 根据工号,表单号获取所有表单信息
        /// </summary>
        /// <returns></returns>
        public async Task<PerformHistoryDto> GetHistoryDataDetail(string worknumber, int formDataId)
        {
            PerformHistoryDto historyDto = new PerformHistoryDto();
            Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfGetPerformanceHistoryFormContent_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
                };

            var requestBody = new
            {
                ___format = "json",
                ___filter = $"formSubjectId eq '{worknumber}' and formDataId eq '{formDataId}'",
                ___select = "formDataId,formTitle,formTemplateId,formReviewStartDate,formLastModifiedDate,currentStep,formSubjectId,formReviewDueDate,formDataStatus,formReviewEndDate,formLastContent/formContentId,formLastContent/formDataId,formLastContent/pmReviewContentDetail/formContentId,formLastContent/pmReviewContentDetail/formDataId,formLastContent/pmReviewContentDetail/customSections/sectionIndex,formLastContent/pmReviewContentDetail/customSections/formContentId,formLastContent/pmReviewContentDetail/customSections/formDataId,formLastContent/pmReviewContentDetail/customSections/sectionName,formLastContent/pmReviewContentDetail/customSections/customElement/elementKey,formLastContent/pmReviewContentDetail/customSections/customElement/type,formLastContent/pmReviewContentDetail/customSections/customElement/sectionIndex,formLastContent/pmReviewContentDetail/customSections/customElement/name,formLastContent/pmReviewContentDetail/customSections/customElement/value,formLastContent/pmReviewContentDetail/customSections/customElement/checked,formLastContent/pmReviewContentDetail/customSections/customElement/formDataId,formLastContent/pmReviewContentDetail/objectiveSections/sectionIndex,formLastContent/pmReviewContentDetail/objectiveSections/formContentId,formLastContent/pmReviewContentDetail/objectiveSections/formDataId,formLastContent/pmReviewContentDetail/objectiveSections/sectionName,formLastContent/pmReviewContentDetail/objectiveSections/sectionDescription,formLastContent/pmReviewContentDetail/objectiveSections/objectives/sectionIndex,formLastContent/pmReviewContentDetail/objectiveSections/objectives/itemId,formLastContent/pmReviewContentDetail/objectiveSections/objectives/formContentId,formLastContent/pmReviewContentDetail/objectiveSections/objectives/formDataId,formLastContent/pmReviewContentDetail/objectiveSections/objectives/name,formLastContent/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/sectionIndex,formLastContent/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/itemId,formLastContent/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/formDataId,formLastContent/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/label,formLastContent/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/value,formLastContent/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/fieldId,formLastContent/pmReviewContentDetail/objectiveSections/objectives/customElement/elementKey,formLastContent/pmReviewContentDetail/objectiveSections/objectives/customElement/type,formLastContent/pmReviewContentDetail/objectiveSections/objectives/customElement/sectionIndex,formLastContent/pmReviewContentDetail/objectiveSections/objectives/customElement/itemId,formLastContent/pmReviewContentDetail/objectiveSections/objectives/customElement/formDataId,formLastContent/pmReviewContentDetail/objectiveSections/objectives/customElement/name,formLastContent/pmReviewContentDetail/objectiveSections/objectives/customElement/value,formLastContent/pmReviewContentDetail/competencySections/sectionIndex,formLastContent/pmReviewContentDetail/competencySections/formDataId,formLastContent/pmReviewContentDetail/competencySections/sectionName,formLastContent/pmReviewContentDetail/competencySections/sectionDescription,formLastContent/pmReviewContentDetail/competencySections/competencies/sectionIndex,formLastContent/pmReviewContentDetail/competencySections/competencies/itemId,formLastContent/pmReviewContentDetail/competencySections/competencies/formContentId,formDataId,formLastContent/pmReviewContentDetail/competencySections/competencies/description,formLastContent/pmReviewContentDetail/competencySections/competencies/name,formLastContent/pmReviewContentDetail/competencySections/competencies/customElement/elementKey,formLastContent/pmReviewContentDetail/competencySections/competencies/customElement/type,formLastContent/pmReviewContentDetail/competencySections/competencies/customElement/sectionIndex,formLastContent/pmReviewContentDetail/competencySections/competencies/customElement/itemId,formLastContent/pmReviewContentDetail/competencySections/competencies/customElement/formDataId,formLastContent/pmReviewContentDetail/competencySections/competencies/customElement/name,formLastContent/pmReviewContentDetail/competencySections/competencies/customElement/value,formRouteMap/routeStep/routeSubStep/userId,formRouteMap/routeStep/routeSubStep/userRole,formRouteMap/routeStep/routeSubStep/userFullName,formRouteMap/routeStep/routeSubStep/currentStep,formRouteMap/routeStep/formDataId,formRouteMap/routeStep/stepType,formRouteMap/routeStep/stepId,formRouteMap/routeStep/userFullName,formRouteMap/routeStep/userId,formRouteMap/routeStep/current,formRouteMap/routeStep/stepName,formRouteMap/routeStep/userRole,formLastContent/pmReviewContentDetail/summarySection/overallFormRating/ratingLabel,formLastContent/pmReviewContentDetail/summarySection/overallFormRating/textRating",
                ___expand = "formLastContent/pmReviewContentDetail/customSections/customElement,formLastContent/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails,formLastContent/pmReviewContentDetail/objectiveSections/objectives/customElement,formLastContent/pmReviewContentDetail/competencySections/competencies/customElement,formRouteMap/routeStep/routeSubStep,formLastContent/pmReviewContentDetail/summarySection/overallFormRating"
            };
            var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
            var result = await _nPRestHttp.ESBPostAsync<SFLastFormResponse.SFLastFormTitle>(_esbSFTodoGetUrl, requestBodyStr, dic);

            var formData = result?.d.results[0]?.formLastContent?.pmReviewContentDetail?.results[0];
            var steps = result.d.results[0].formRouteMap?.routeStep?.results;
            var needAdds = new List<PerformStepEntity>();
            for (int i = 0; i < steps.Count(); i++)
            {
                if (steps[i].stepName == "绩效校准" || steps[i].stepName == "员工确认绩效结果")
                {
                    continue;
                }
                string name = steps[i].userFullName;
                string userid = steps[i].userId;
                if (string.IsNullOrEmpty(name) && steps[i].routeSubStep?.results != null)
                {
                    foreach (var item in steps[i].routeSubStep.results)
                    {
                        needAdds.Add(new PerformStepEntity()
                        {
                            Id = Guid.NewGuid().ToString(),
                            FormDataId = steps[i].formDataId,
                            StepId = steps[i].stepId,
                            StepName = steps[i].stepName,
                            StepNumber = i + 1,
                            UserName = item.userFullName,
                            WorkNumber = item.userId,
                            UserRole = item.userRole
                        });
                    }
                }
                else
                {
                    needAdds.Add(new PerformStepEntity()
                    {
                        Id = Guid.NewGuid().ToString(),
                        FormDataId = steps[i].formDataId,
                        StepId = steps[i].stepId,
                        StepName = steps[i].stepName,
                        StepNumber = i + 1,
                        UserName = name,
                        WorkNumber = userid,
                        UserRole = steps[i].userRole
                    });
                }
            }

            // 判断待办是否存在
            var user = _dbPlatform.Queryable<Users>().First(t => t.WorkNumber == worknumber);
            var applyJob = _dbPlatform.Queryable<UserExtension>().First(t => t.Sapemployeeid == worknumber)?.Employeepostname;
            historyDto.OrgName = user?.FullPathText;
            historyDto.SubjectName = user?.UserName;
            historyDto.ApplyJob = applyJob;
            historyDto.SubjectId = worknumber;
            historyDto.FormTitle = result?.d.results[0]?.formTitle;
            historyDto.Steps = needAdds.ToList();
            historyDto.FormData = formData;
            return historyDto;
        }


        #region 私有方法
        /// <summary>
        /// 获取表单数据
        /// </summary>
        /// <param name="formDataId"></param>
        /// <returns></returns>
        private async Task<PerformFormDataEntity> GetFormTitle(PerformanceEntity item, string token)
        {
            PerformFormDataEntity needAdds = null;

            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfGetInroutePerformanceFormContent_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem },
                    { "Authorization", "Bearer "+ token }
                };

                var requestBody = new
                {
                    ___format = "json",
                    ___filter = $"formDataId eq '{item.FormDataId}'",
                    ___expand = "formContents/pmReviewContentDetail/objectiveSections,formContents/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/elementListValues,formContents/pmReviewContentDetail/competencySections/competencies/customElement,formContents/pmReviewContentDetail/customSections/customElement/elementListValues,formContents/pmReviewContentDetail/summarySection/overallFormRating",
                    ___select = "formContents/pmReviewContentDetail/objectiveSections/sectionName,formContents/pmReviewContentDetail/objectiveSections/sectionWeight,formContents/pmReviewContentDetail/objectiveSections/sectionDescription,formContents/pmReviewContentDetail/objectiveSections/sectionIndex,formContents/pmReviewContentDetail/objectiveSections/objectives/name,formContents/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/label,formContents/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/value,formContents/pmReviewContentDetail/objectiveSections/objectives/objectiveDetails/fieldId,formContents/pmReviewContentDetail/objectiveSections/sectionName,formContents/pmReviewContentDetail/objectiveSections/sectionIndex,formContents/pmReviewContentDetail/objectiveSections/formContentId,formContents/pmReviewContentDetail/objectiveSections/formDataId,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/elementKey,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/sectionIndex,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/itemId,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/formContentId,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/formDataId,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/type,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/valueKey,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/value,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/name,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/elementListValues/name,formContents/pmReviewContentDetail/objectiveSections/objectives/customElement/elementListValues/value,formContents/pmReviewContentDetail/objectiveSections/sectionIndex,formContents/pmReviewContentDetail/objectiveSections/sectionName,formContents/pmReviewContentDetail/objectiveSections/objectives/itemId,formContents/pmReviewContentDetail/objectiveSections/objectives/sectionIndex,formContents/pmReviewContentDetail/objectiveSections/objectives/name,formContents/pmReviewContentDetail/competencySections/sectionName,formContents/pmReviewContentDetail/competencySections/sectionDescription,formContents/pmReviewContentDetail/competencySections/competencies/name,formContents/pmReviewContentDetail/competencySections/competencies/description,formContents/pmReviewContentDetail/competencySections/competencies/customElement/elementKey,formContents/pmReviewContentDetail/competencySections/competencies/customElement/sectionIndex,formContents/pmReviewContentDetail/competencySections/competencies/customElement/sectionIndex,formContents/pmReviewContentDetail/competencySections/competencies/customElement/itemId,formContents/pmReviewContentDetail/competencySections/competencies/customElement/formContentId,formContents/pmReviewContentDetail/competencySections/competencies/customElement/formDataId,formContents/pmReviewContentDetail/competencySections/competencies/customElement/name,formContents/pmReviewContentDetail/competencySections/competencies/customElement/valueKey,formContents/pmReviewContentDetail/competencySections/competencies/customElement/value,formContents/pmReviewContentDetail/competencySections/competencies/customElement/type,formContents/pmReviewContentDetail/customSections/sectionIndex,formContents/pmReviewContentDetail/customSections/sectionName,formContents/pmReviewContentDetail/customSections/customElement/formContentId,formContents/pmReviewContentDetail/customSections/customElement/formDataId,formContents/pmReviewContentDetail/customSections/customElement/type,formContents/pmReviewContentDetail/customSections/customElement/name,formContents/pmReviewContentDetail/customSections/customElement/elementKey,formContents/pmReviewContentDetail/customSections/customElement/valueKey,formContents/pmReviewContentDetail/customSections/customElement/value,formContents/pmReviewContentDetail/customSections/customElement/sectionIndex,formContents/pmReviewContentDetail/customSections/customElement/itemId,formContents/pmReviewContentDetail/customSections/customElement/checked,formContents/pmReviewContentDetail/customSections/customElement/elementListValues/name,formContents/pmReviewContentDetail/customSections/customElement/elementListValues/value,formContents/pmReviewContentDetail/summarySection/overallFormRating/ratingLabel,formContents/pmReviewContentDetail/summarySection/overallFormRating/textRating"
                };
                var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");
                var result = await _nPRestHttp.ESBPostAsync<SFPerformDto.SFFormTitleResponse.SFFormTitle>(_esbSFGetUrl, requestBodyStr, dic);
                int count = result?.d?.results?.Count() ?? 0;
                if (count > 0)
                {
                    needAdds = new PerformFormDataEntity()
                    {
                        TodoEntryId = item.TodoEntryId,
                        FormData = JsonConvert.SerializeObject(result?.d.results[0]?.formContents?.results[0]?.pmReviewContentDetail?.results[0]),
                        FormDataId = item.FormDataId,
                        CreateDate = DateTime.Now,
                    };
                }
            }
            catch (Exception)
            {
            }
            return needAdds;
        }

        /// <summary>
        /// 获取审批步骤
        /// </summary>
        /// <param name="formDataId"></param>
        /// <returns></returns>
        private async Task<List<PerformStepEntity>> GetFormStep(int formDataId, string token)
        {
            List<PerformStepEntity> needAdds = new List<PerformStepEntity>();
            try
            {
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfRoutemap_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem },
                    { "Authorization", "Bearer "+token }
                };
                var requestBody = new
                {
                    ___format = "json",
                    ___filter = $"formDataId eq '{formDataId}'",
                    ___expand = "formRouteMap/routeStep/routeSubStep",
                    ___select = "formRouteMap/routeStep/routeSubStep/userId,formRouteMap/routeStep/routeSubStep/userRole,formRouteMap/routeStep/routeSubStep/userFullName,formRouteMap/routeStep/routeSubStep/currentStep,formRouteMap/routeStep/formDataId,formRouteMap/routeStep/stepType,formRouteMap/routeStep/stepId,formRouteMap/routeStep/userFullName,formRouteMap/routeStep/userId,formRouteMap/routeStep/current,formRouteMap/routeStep/stepName,formRouteMap/routeStep/userRole"
                };
                var requestBodyStr = JsonConvert.SerializeObject(requestBody).Replace("___", "$");

                var result = await _nPRestHttp.ESBPostAsync<SFPerformDto.SFFormStepResponse.SFFormStep>(_esbSFGetUrl, requestBodyStr, dic);
                int count = result?.d?.results?.Count() ?? 0;
                if (count > 0)
                {
                    var steps = result.d.results[0].formRouteMap?.routeStep?.results;

                    for (int i = 0; i < steps.Count(); i++)
                    {
                        if (steps[i].stepName == "绩效校准" || steps[i].stepName == "员工确认绩效结果")
                        {
                            continue;
                        }
                        string name = steps[i].userFullName;
                        string userid = steps[i].userId;
                        if (string.IsNullOrEmpty(name) && steps[i].routeSubStep?.results != null)
                        {
                            foreach (var item in steps[i].routeSubStep.results)
                            {
                                needAdds.Add(new PerformStepEntity()
                                {
                                    Id = Guid.NewGuid().ToString(),
                                    FormDataId = steps[i].formDataId,
                                    StepId = steps[i].stepId,
                                    StepName = steps[i].stepName,
                                    StepNumber = i + 1,
                                    UserName = item.userFullName,
                                    WorkNumber = item.userId,
                                    UserRole = item.userRole
                                });
                            }
                        }
                        else
                        {
                            needAdds.Add(new PerformStepEntity()
                            {
                                Id = Guid.NewGuid().ToString(),
                                FormDataId = steps[i].formDataId,
                                StepId = steps[i].stepId,
                                StepName = steps[i].stepName,
                                StepNumber = i + 1,
                                UserName = name,
                                WorkNumber = userid,
                                UserRole = steps[i].userRole
                            });
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
            return needAdds;
        }

        /// <summary>
        /// 获取token
        /// </summary>
        /// <param name="workNumber">员工工号</param>
        /// <returns></returns>
        private string GetToken(string workNumber)
        {
            string result = string.Empty;
            try
            {
                // 获取Assertion
                var assertion = GetAssertion(workNumber);
                Dictionary<string, string> dic = new Dictionary<string, string>()
                {
                    { "serviceName", "S_XXX_SF_SfToken_S" },
                    { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
                };
                var requestBody = new
                {
                    company_id = _companyId,
                    client_id = _clientId,
                    grant_type = "urn:ietf:params:oauth:grant-type:saml2-bearer",
                    assertion = assertion
                };

                var requestBodyStr = JsonConvert.SerializeObject(requestBody);
                var resultObj = _nPRestHttp.ESBPostAsync<JObject>(_esbSFTokenUrl, requestBodyStr, dic).Result;

                if (resultObj != null && resultObj.ContainsKey("access_token"))
                {
                    result = resultObj["access_token"].ToString();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }

        private string GetAssertion(string workNumber)
        {
            // 获取Assertion
            Dictionary<string, string> dic = new Dictionary<string, string>()
            {
                { "serviceName", "S_XXX_SF_SfAssertion_S" },
                { "sourceSystem", string.IsNullOrEmpty(_sourceSystem) ? "BPMNEW" : _sourceSystem }
            };
            var requestBody = new
            {
                client_id = _clientId,
                private_key = _privatekey,
                token_url = _tokenUrl,
                user_id = workNumber
            };

            var requestBodyStr = JsonConvert.SerializeObject(requestBody);
            var result = _nPRestHttp.ESBPostAsync(_esbSFTokenUrl, requestBodyStr, dic).Result;
            return result;
        }

        /// <summary>
        /// 将SF日期转成DateTime
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private DateTime? ToSFDateTime(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return null;
            }

            long millSeconds = 0;
            str = str.Replace("/Date(", string.Empty).Replace(")/", string.Empty);
            if (str.Length > 13) { str = str.Substring(0, 13); }
            bool isTrue = long.TryParse(str, out millSeconds);
            if (isTrue)
            {
                if (str.Length >= 13)
                {
                    return DateTimeOffset.FromUnixTimeMilliseconds(millSeconds).ToLocalTime().DateTime;
                }
                else if (str.Length == 10)
                {
                    return DateTimeOffset.FromUnixTimeSeconds(millSeconds).ToLocalTime().DateTime;
                }

                return null;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 将日期转成SF需要的str
        /// 注意，推送给SF的数据，日期要加8H
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private string ToSFStr(DateTime date, bool IsPush = false)
        {
            if (date == null)
            {
                return "0";
            }

            if (IsPush)
            {
                date = date.AddHours(8);
            }

            DateTimeOffset dateTime = new DateTimeOffset(date);
            return string.Format("/Date({0})/", dateTime.ToUnixTimeMilliseconds());
        }

        #endregion
    }

    public class TestEmailDto
    {
        public string email { get; set; }
        public string title { get; set; }
    }
}
